package com.rpay.web.controller.user;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.rpay.common.dto.auth.AuthDTO;
import com.rpay.common.dto.sms.SmsCodeDTO;
import com.rpay.common.dto.user.UserDTO;
import com.rpay.common.dto.user.UserVerifyDTO;
import com.rpay.common.enums.PcsResultCode;
import com.rpay.common.enums.SmsCodeEnum;
import com.rpay.common.enums.SmsTypeEnum;
import com.rpay.common.exception.UserException;
import com.rpay.common.util.FileUtil;
import com.rpay.common.util.Md5Util;
import com.rpay.common.vo.PcsResult;
import com.rpay.service.auth.IAuthService;
import com.rpay.service.config.ServiceThreadLocal;
import com.rpay.service.sms.ISmsCodeService;
import com.rpay.service.user.IUserService;
import com.rpay.service.user.IUserTokenService;
import com.rpay.service.user.IUserVerifyService;
import com.rpay.web.controller.BaseController;
import com.rpay.web.interceptor.authentic.AccessControl;
import com.rpay.web.interceptor.authentic.AccessControlType;
import com.rpay.web.param.ModifyPwd;
import com.rpay.web.service.UserService;
import org.hibernate.validator.constraints.NotBlank;
import org.json.JSONArray;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.validation.constraints.NotNull;
import java.io.IOException;
import java.util.List;
import java.util.Map;

/**
 * Title：
 * Description
 *
 * @author fxg06 on 2018/5/5
 * @version 1.0
 */
@RestController
@RequestMapping(value = "api/user")
@AccessControl(type = {AccessControlType.SECRET, AccessControlType.ACCESS_TOKEN})
@Validated
public class UserAuthController extends BaseController {

    @Value("${file.img.location}")
    private String location;
    @Value("${file.img.url}")
    private String imgUrl;

    @Value("${ripple.wallet.addr}")
    private String rippleWalletAddr;

    @Autowired
    private UserService userService;
    @Autowired
    private IUserTokenService iUserTokenService;
    @Autowired
    private IUserVerifyService iUserVerifyService;
    @Autowired
    private IUserService iUserService;
    @Autowired
    private IAuthService iAuthService;
    @Autowired
    private ISmsCodeService iSmsCodeService;
    
    @PostMapping(value = "logout")
    public PcsResult logout() {
        iUserTokenService.deleteToken(ServiceThreadLocal.getAccessToken());
        return newResult();
    }

    @PostMapping(value = "ocr")
    @AccessControl(type = AccessControlType.ACCESS_TOKEN)
    public PcsResult idcardOcr(@RequestParam("file") MultipartFile file, @RequestParam String side) {
        try {
            String image = FileUtil.base64(file);
            UserVerifyDTO userVerifyDTO = iUserVerifyService.ocr(image, side);
            if (userVerifyDTO == null) {
                FileUtil.upload(location, imgUrl, file);
            }
        } catch (IOException e) {
        }
        return new PcsResult();
    }

    @PostMapping(value = "bindPhone")
    public PcsResult bindPhone(@RequestParam @NotBlank(message = "手机号不能为空") String phone,
                               @RequestParam @NotBlank(message = "验证码不能为空") String code) {
        userService.bindPhone(phone, code);
        return newResult();
    }

    @PostMapping(value = "verify")
    public PcsResult verify(@RequestParam @NotBlank(message = "姓名不能为空") String name,
                            @RequestParam @NotBlank(message = "身份证不能为空") String idcard) {
        UserVerifyDTO userVerifyDTO = iUserVerifyService.verify(name, idcard);
        return PcsResult.build(userVerifyDTO);
    }

    @PutMapping(value = "modifyPwd")
    @AccessControl(type = AccessControlType.ACCESS_TOKEN)
    public PcsResult modifyPwd(@Validated @RequestBody ModifyPwd modifyPwd) {
        UserDTO userDTO = getUser();
        SmsCodeDTO smsCodeDTO = new SmsCodeDTO();
        if (modifyPwd.getType().equals(SmsTypeEnum.MAIL.getCode())) {
            smsCodeDTO.setType(SmsTypeEnum.MAIL.getCode());
            smsCodeDTO.setReceiver(userDTO.getEmail());
        } else {
            smsCodeDTO.setType(SmsTypeEnum.PHONE.getCode());
            smsCodeDTO.setReceiver(userDTO.getPhone());
        }
        smsCodeDTO.setVerifyType(SmsCodeEnum.MODIFY_PWD.getCode());
        smsCodeDTO.setCode(modifyPwd.getCode());

        userDTO.setPassword(Md5Util.encrypt(modifyPwd.getPassword()));
        userService.modifyPwd(userDTO,smsCodeDTO);
        return newResult();
    }

    @PostMapping(value = "googleKey")
    public PcsResult googleKey() {
        return PcsResult.build(iAuthService.createAuth(getUser().getEmail()));
    }

    @PutMapping(value = "bindGoogleKey")
    public PcsResult bindGoogleKey(@RequestParam @NotNull(message = "code不能为空") Integer code, @RequestParam @NotBlank(message = "密匙不能为空") String secretKey) {
        UserDTO user = getUser();
        AuthDTO authDTO = iAuthService.getAuthDTO(user.getEmail(), secretKey);
        iAuthService.verifyAuth(secretKey, code);
        UserDTO userDTO = new UserDTO();
        userDTO.setId(ServiceThreadLocal.getUserId());
        userDTO.setSecretKey(secretKey);
        iUserService.updateUser(userDTO);
        iAuthService.updateValid(authDTO.getId());
        return newResult();
    }

    @PutMapping(value = "verifyGoogleKey")
    public PcsResult verifyGoogleKey(@RequestParam @NotNull(message = "code不能为空") Integer code) {
        UserDTO userDTO = getUser();
        iAuthService.verifyAuth(userDTO.getSecretKey(), code);
        return newResult();
    }

    @GetMapping(value = "info")
    public PcsResult user() {
        UserDTO userDTO = iUserService.getUserById(ServiceThreadLocal.getUserId());
        return PcsResult.build(userDTO);
    }

    @PutMapping(value = "tradePwd")
    public PcsResult setTradePwd(@RequestParam @NotBlank(message = "交易密码不能为空") String tradePassword, @RequestParam @NotNull(message = "验证码不能为空") String code,@RequestParam @NotBlank(message = "验证码类型不能为空") String type) {
        UserDTO user = getUser();
        if (SmsTypeEnum.MAIL.getCode().equals(type)) {
            iSmsCodeService.verifyMail(SmsCodeEnum.TRADE_PWD.getCode(), user.getEmail(), code);
        } else {
            iAuthService.verifyAuth(user.getSecretKey(), Integer.valueOf(code));
        }
        user.setTradePassword(Md5Util.encrypt(tradePassword));
        iUserService.updateUser(user);
        return newResult();
    }

    @GetMapping(value = "team")
    public PcsResult team() {
        UserDTO userDTO = iUserService.getUserById(ServiceThreadLocal.getUserId());
        List<UserDTO> list = iUserService.getAllUser(userDTO.getTeamKey());
        Map<String, Object> map = getChild(userDTO, list);
        return new PcsResult(map);
    }

    private Map getChild(UserDTO userDTO, List<UserDTO> list) {
        Map<String, Object> map = Maps.newHashMap();
        map.put("email", userDTO.getEmail());
        map.put("level", userDTO.getLevel());
        map.put("id", userDTO.getId());
        List<Map> mapList = Lists.newArrayList();
        int count = 0;
        if (!CollectionUtils.isEmpty(list)) {
            for (UserDTO user : list) {
                if (user.getParentId().equals(userDTO.getId())) {
                    count ++;
                    Map childObj = getChild(user, list);
                    mapList.add(childObj);
                }
            }
        }
        map.put("count", count);
        map.put("child", mapList);
        return map;
    }

    @GetMapping(value = "investAddr")
    public PcsResult investAddr() {
        return new PcsResult(rippleWalletAddr);
    }
}
